
import Throttling from '../../utils/throttling';
import deepCopy from '../../utils/deepCopy';

function computedWatchInner (tableRef) {
  this.tableWatch(tableRef);
}

export default option => {
  let {
    data,
  } = option;
  let dataStep = {};
  let computedStep = {};
  let watchStep = {};
  function tablePublic (object, tableRef) {
    let {column, key, tableColumn, ref, option, select} = object;
    let tableColumnStep = [];
    if (tableColumn && !isNaN(tableColumn)) {
      for (let i = 0; i < tableColumn; i++) {
        tableColumnStep.push(column[i]);
      }
      delete object.tableColumn;
    }
    return {
      page: 1,
      pageSizes: [5, 10, 20, 50, 100],
      rows: 10,
      total: 0,
      layout: 'total, sizes, prev, pager, next, jumper',
      small: false,
      muti: true,
      loading: false,
      summary: false,
      spanMethod: undefined,
      data: [],
      option: option || {},
      select: select || {},
      multiSelect: false,
      multipleSelection: [],
      key: key || column[0].prop,
      ref: ref || tableRef,
      tableColumn: tableColumnStep.length ? tableColumnStep : column,
      tableColumnAll: column,
    };
  }
  function tableItem (data, tableRef) {
    let {column} = data;
    let autoVueTableRefOld = {};
    computedStep['autoVue_' + tableRef] = null;
    let comp = {};
    let filter = [];
    let elInputNumberFilter = ElInputNumberFilter();
    for (let item of column) {
      let {search, elInputNumber} = item;
      if (search) {
        let prop = item.searchName || item.prop;
        if (/^show_/.test(prop)) {
          prop = prop.replace('show_', '');
        }
        switch (item.type) {
        case 'dateRange':
        case 'DateRange':
          dataStep[`autoVue_${tableRef}_` + prop] = [];
          autoVueTableRefOld[prop] = [];
          comp[prop] = 'dateRange';
          break;
        case 'custom':
          if (item.searchInitValue && item.searchInitValue.constructor !== Function) {
            console.error('AutoVueTable 中 custom属性 声明一个不是函数的 searchInitValue ！');
          }
          dataStep[`autoVue_${tableRef}_` + prop] = item.searchInitValue ? item.searchInitValue() : '';
          autoVueTableRefOld[prop] = item.searchInitValue ? item.searchInitValue() : '';
          comp[prop] = item.searchAfter;
          break;
        default:
          dataStep[`autoVue_${tableRef}_` + prop] = '';
          autoVueTableRefOld[prop] = '';
          comp[prop] = '';
        }
        watchStep[ `autoVue_${tableRef}_${prop}` ] = function () {
          let _this = this;
          Throttling(computedWatchInner, {
            throttlingTime: 500,
            context: _this,
            data: tableRef,
          });
        };
      }
      dataStep['autoVue_' + tableRef + '_SetSearch'] = autoVueTableRefOld;
      if (elInputNumber && (isNaN(elInputNumber.max) || isNaN(elInputNumber.min))) {
        elInputNumberFilter.data.push(item.prop);
      }
    }
    if (elInputNumberFilter.data.length !== 0) {
      filter.push(elInputNumberFilter);
    }
    data.filter = filter;
    data.ref = tableRef;
    computedStep['autoVue_' + tableRef] = function () {
      let option = {};
      for (let index in comp) {
        if (comp.hasOwnProperty(index)) {
          switch (comp[index]) {
          case 'dateRange':
            let date = this[`autoVue_${tableRef}_` + index];
            if (date === null) {
              option[index + '_start'] = '';
              option[index + '_end'] = '';
            } else if (data.length !== 0) {
              option[index + '_start'] = new Date(date[0]).getTime();
              option[index + '_end'] = new Date(date[1]).getTime();
            } else {
              option[index + '_start'] = '';
              option[index + '_end'] = '';
            }
            break;
          default:
            if (comp[index].constructor === Function) {
              let array = deepCopy(this[`autoVue_${tableRef}_` + index]);
              option[index] = comp[index](array);
            } else {
              option[index] = this[`autoVue_${tableRef}_` + index];
            }
          }
        }
      }
      return option;
    };
    return data;
  }
  for (let tableRef in data) {
    if (data.hasOwnProperty(tableRef) && /^table/.test(tableRef)) {
      if (typeof data[tableRef].column === 'undefined') {
        data[tableRef] = {column: data[tableRef]};
      }
      data[tableRef] = tableItem(data[tableRef], tableRef);
      data[tableRef] = {
        ...tablePublic(data[tableRef], tableRef),
        ...data[tableRef],
      };
      delete data[tableRef].column;
    }
  }
  option.data = {
    ...option.data,
    ...dataStep,
  };
  option.computed = {
    ...option.computed,
    ...computedStep,
  };
  option.watch = {
    ...option.watch,
    ...watchStep,
  };
  option.methods['tableWatch'] = async function (tableRef) {
    let {
      page,
      rows,
    } = this[tableRef];
    let option = Object.assign({}, this['autoVue_' + tableRef]);
    this[tableRef].loading = true;
    try {
      let response = await this.p(this[tableRef].url, {
        method: 'post',
        headers: {
          sLoading: true,
        },
        data: {
          ...this[tableRef].option,
          ...option,
          pageNumber: page,
          pageSize: rows,
        },
      });
      let data = response.contentList;
      let total = response.totals;
      if (this[tableRef].ids && this[tableRef].ids.length > 0) {
        let rows = [];
        data.find((value) => {
          if (this[tableRef].ids.indexOf(value[this[tableRef].key]) !== -1) {
            rows.push(value);
            this[tableRef].ids.splice(this[tableRef].ids.indexOf(value[this[tableRef].key]), 1);
          }
        });
        rows.forEach(row => {
          this.$refs[tableRef].$refs[tableRef].toggleRowSelection(row);
        });
      }
      if (this[tableRef].cb) {
        this[tableRef].cb.call(this, {
          data,
          total,
        });
        return;
      }
      this[tableRef].data = tableFilter(this[tableRef].filter, data);
      this[tableRef].total = total;
    } finally {
      this[tableRef].loading = false;
    }
  };
  option.methods['tableIds'] = function (tableRef) {
    let ids = [];
    for (let item of this[tableRef].multipleSelection) {
      ids.push(item.id);
    }
    if (typeof this[tableRef].ids !== 'undefined') {
      return [
        ...ids,
        ...this[tableRef].ids,
      ];
    } else {
      return ids;
    }
  };
  option.methods['tableClear'] = function (tableRef) {
    this[tableRef].page = 1;
    this[tableRef].rows = 10;
    this[tableRef].total = 0;
    this[tableRef].option = {};
    this[tableRef].data = [];
    tableMutiClear.call(this, tableRef);
  };
  option.methods['tableMutiClear'] = tableMutiClear;
  option.methods['tableSetData'] = function (tableRef, json) {
    let data = [];
    let total = 0;
    if (json.constructor !== Array) {
      data = json.contentList;
      total = json.totals;
    } else {
      data = json;
      total = json.length;
    }
    this[tableRef].data = tableFilter(this[tableRef].filter, data);
    this[tableRef].total = total;
  };
  option.methods['tableSetSearch'] = function (tableRef) {
    let old = this['autoVue_' + tableRef + '_SetSearch'];
    if (!old) {
      console.error(tableRef + '  中 尝试 tableSetSearch 但是 没有获取到对应的 old值！');
    } else {
      let pre = 'autoVue_' + tableRef + '_';
      for (let index in old) {
        if (old.hasOwnProperty(index)) {
          this[pre + index] = old[index];
        }
      }
    }
  };
};

function tableMutiClear (tableRef) {
  if (typeof this.$refs[tableRef] !== 'undefined') {
    this.$refs[tableRef].$refs[tableRef].clearSelection();
  } else {
    console.warn('存在 tableRef 为空！ 清空 tableClear 无效！' + tableRef);
  }
}
function tableFilter (filter, data) {
  if (filter.length !== 0) {
    let step = [];
    for (let value of data) {
      filter.forEach(item => {
        value = item.func(value);
      });
      step.push(value);
    }
    data = step;
  }
  return data;
}
function ElInputNumberFilter () {
  return {
    data: [],
    func: function (value) {
      this.data.forEach(item => {
        if (!value[item]) {
          console.error(item + '  没有找到！！  ElInputNumberFilter ' + (new Date()).toLocaleString());
          return;
        }
        value[item] = parseInt(value[item]);
        value['OldNumber_' + item] = value[item];
      });
      return value;
    },
  };
}
